package com.zc.changeskin;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.view.View;
import com.zc.changeskin.attr.SkinAttrSupport;
import com.zc.changeskin.attr.SkinView;
import com.zc.changeskin.callback.ISkinChangingCallback;
import com.zc.changeskin.utils.L;
import com.zc.changeskin.utils.PrefUtils;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import pad.stand.com.haidiyun.www.common.P;

/**
 */
public class SkinManager {
	private Context mContext;
	private Resources mResources;
	private ResourceManager mResourceManager;
	private PrefUtils mPrefUtils;
	private boolean usePlugin;
	private String mSuffix = "";
	private String mCurPluginPath;
	private String mCurPluginPkg;
	private static SkinManager sInstance;
	// 加入Activity和View皮肤组
	private List<Object> mActivities = new ArrayList<Object>();

	private SkinManager() {
	}

	public static synchronized SkinManager getInstance() {
		if (sInstance == null) {
			synchronized (SkinManager.class) {
				if (sInstance == null) {
					sInstance = new SkinManager();
				}
			}
		}
		return sInstance;
	}

	public void init(Context context) {
		mContext = context.getApplicationContext();
		mPrefUtils = new PrefUtils(mContext);

		String skinPluginPath = mPrefUtils.getPluginPath();
		String skinPluginPkg = mPrefUtils.getPluginPkgName();
		mSuffix = mPrefUtils.getSuffix();

		if (!validPluginParams(skinPluginPath, skinPluginPkg))
			return;

		try {
			loadPlugin(skinPluginPath, skinPluginPkg, mSuffix);
			mCurPluginPath = skinPluginPath;
			mCurPluginPkg = skinPluginPkg;
		} catch (Exception e) {
			mPrefUtils.clear();
			e.printStackTrace();
		}
	}

	private PackageInfo getPackageInfo(String skinPluginPath) {
		PackageManager pm = mContext.getPackageManager();
		return pm.getPackageArchiveInfo(skinPluginPath,
				PackageManager.GET_ACTIVITIES);
	}

	private void loadPlugin(String skinPath, String skinPkgName, String suffix)
			throws Exception {
		AssetManager assetManager = AssetManager.class.newInstance();
		Method addAssetPath = assetManager.getClass().getMethod("addAssetPath",
				String.class);
		addAssetPath.invoke(assetManager, skinPath);
		Resources superRes = mContext.getResources();
		mResources = new Resources(assetManager, superRes.getDisplayMetrics(),
				superRes.getConfiguration());
		mResourceManager = new ResourceManager(mResources, skinPkgName, suffix);
		usePlugin = true;
	}

	private boolean validPluginParams(String skinPath, String skinPkgName) {
		if (TextUtils.isEmpty(skinPath) || TextUtils.isEmpty(skinPkgName)) {
			return false;
		}

		File file = new File(skinPath);
		if (!file.exists())
			return false;

		PackageInfo info = getPackageInfo(skinPath);
		if (!info.packageName.equals(skinPkgName))
			return false;
		return true;
	}

	private void checkPluginParamsThrow(String skinPath, String skinPkgName) {
		if (!validPluginParams(skinPath, skinPkgName)) {
			throw new IllegalArgumentException(
					"skinPluginPath or skinPkgName not valid ! ");
		}
	}

	public void removeAnySkin() {
		L.e("removeAnySkin");
		clearPluginInfo();
		notifyChangedListeners();
	}

	public boolean needChangeSkin() {
		return usePlugin || !TextUtils.isEmpty(mSuffix);
	}

	public ResourceManager getResourceManager() {
		if (!usePlugin) {
			mResourceManager = new ResourceManager(mContext.getResources(),
					mContext.getPackageName(), mSuffix);
		}
		return mResourceManager;
	}

	/**
	 * 应用内换肤，传入资源区别的后�? *
	 *
	 * @param suffix
	 */
	public void changeSkin(String suffix) {
		clearPluginInfo();// clear before
		mSuffix = suffix;
		mPrefUtils.putPluginSuffix(suffix);
		notifyChangedListeners();
	}

	private void clearPluginInfo() {
		mCurPluginPath = null;
		mCurPluginPkg = null;
		usePlugin = false;
		mSuffix = null;
		mPrefUtils.clear();
		mActivities.clear();
	}

	private void updatePluginInfo(String skinPluginPath, String pkgName,
								  String suffix) {
		mPrefUtils.putPluginPath(skinPluginPath);
		mPrefUtils.putPluginPkg(pkgName);
		mPrefUtils.putPluginSuffix(suffix);
		mCurPluginPkg = pkgName;
		mCurPluginPath = skinPluginPath;
		mSuffix = suffix;
	}

	public void changeSkin(final String skinPluginPath,
						   final String skinPluginPkg, ISkinChangingCallback callback) {
		changeSkin(skinPluginPath, skinPluginPkg, null, callback);
	}

	/**
	 * 根据suffix选择插件内某套皮肤，默认�?"
	 *
	 * @param skinPluginPath
	 * @param skinPluginPkg
	 * @param suffix
	 * @param callback
	 */
	public void changeSkin(final String skinPluginPath,
						   final String skinPluginPkg, final String suffix,
						   ISkinChangingCallback callback) {
		L.e("changeSkin = " + skinPluginPath + " , " + skinPluginPkg);
		if (callback == null)
			callback = ISkinChangingCallback.DEFAULT_SKIN_CHANGING_CALLBACK;
		final ISkinChangingCallback skinChangingCallback = callback;

		skinChangingCallback.onStart();

		try {
			checkPluginParamsThrow(skinPluginPath, skinPluginPkg);
		} catch (IllegalArgumentException e) {
			skinChangingCallback.onError(new RuntimeException(
					"checkPlugin occur error"));
			return;
		}

		new AsyncTask<Void, Void, Integer>() {
			@Override
			protected Integer doInBackground(Void... params) {
				try {
					loadPlugin(skinPluginPath, skinPluginPkg, suffix);
					return 1;
				} catch (Exception e) {
					e.printStackTrace();
					return 0;
				}

			}

			@Override
			protected void onPostExecute(Integer res) {
				if (res == 0) {
					skinChangingCallback.onError(new RuntimeException(
							"loadPlugin occur error"));
					return;
				}
				try {
					updatePluginInfo(skinPluginPath, skinPluginPkg, suffix);
					notifyChangedListeners();
					skinChangingCallback.onComplete();
				} catch (Exception e) {
					e.printStackTrace();
					skinChangingCallback.onError(e);
				}

			}
		}.execute();
	}

	// Activity
	private void apply(Object activity) {
		List<SkinView>  skinViews = SkinAttrSupport.getSkinViews(activity);
		if (skinViews == null)
			return;
		for (SkinView skinView : skinViews) {
			skinView.apply();
		}
	}


	/**
	 * 绑定view
	 * @param activity
	 * @param id
	 */
	public void register(final Object activity, int id) {
		if (activity instanceof View) {
			mActivities.add(activity);
			((View) activity).findViewById(id).post(new Runnable() {
				@Override
				public void run() {
					apply((View) activity);
				}
			});
		} else {
			P.c("tag-activity异常");
		}
	}
	/**
	 * 绑定activity
	 * @param activity
	 */
	public void register(final Object activity) {
		if (activity instanceof Activity) {
			mActivities.add(activity);
			((Activity) activity).findViewById(android.R.id.content).post(
					new Runnable() {
						@Override
						public void run() {
							apply((Activity) activity);
						}
					});
		} else {
			P.c("tag-view异常");
		}

	}

	/**
	 * Activity
	 *
	 * @param activity
	 */
	public void unregister(Object activity) {
		mActivities.remove(activity);

	}
	public void notifyChangedListeners() {
		for (Object activity : mActivities) {
			if (activity instanceof Activity) {
				apply((Activity) activity);
			} else if (activity instanceof View) {
				apply((View) activity);
			}
		}
	}

	/**
	 * apply for dynamic construct view
	 *
	 * @param view
	 */
	public void injectSkin(View view) {
		List<SkinView> skinViews = new ArrayList<SkinView>();
		SkinAttrSupport.addSkinViews(view, skinViews);
		for (SkinView skinView : skinViews) {
			skinView.apply();
		}
	}

}
